package jdesktop.appbar.win32;

import com.sun.jna.Pointer;
import jdesktop.appbar.AppBar;
import jdesktop.appbar.AppBarModel;
import jdesktop.appbar.DesktopEnvironment;

/**
 * The state shared by different window procedures. The window procedure implementations
 * encapsulate behaviour, while this class encapsulates state. The separation of state from
 * behaviour allows the behaviour (wndProc) to change while maintaining state.
 */
class WndProcState
{

    /**
     * The original window proc that this subclass delegates to.
     */
    protected Pointer delegate;

    /**
     * Set when the window is within the move/size loop.
     */
    private transient boolean movingOrSizing = false;

    /**
     * The dragGuide that implements drag handling.
     */
    private DragGuide dragGuide;

    private DesktopEnvironment environment;

    /**
     * When false, the size of the reserved area is not changed until after
     * the size/move loop. When true, the appbar is sized/positioned as the window changes,
     * potentially causing all other windows on the desktop to resize.
     */
    protected boolean dragAppBarWidthWindow = false;

    private final AppBarModel model;
    private final AppBar    appbar;
    private final WindowMessageHandler windowMessageHandler;


    WndProcState(Pointer delegate, DragGuide dragGuide,
                 DesktopEnvironment environment, AppBar appbar,
                 WindowMessageHandler messageHandler)
    {
        this.delegate = delegate;
        this.dragGuide = dragGuide;
        this.environment = environment;
        this.appbar = appbar;
        this.model = appbar.getAppBarModel();
        this.windowMessageHandler = messageHandler;
    }

    /**
     * Calls the original window class procedure.
     * @param hWnd
     * @param uMsg
     * @param wParam
     * @param lParam
     * @return
     */
    public int callClassWndProc(Pointer hWnd, int uMsg, int wParam, int lParam)
    {
        return CommonWndProc.user32.CallWindowProcW(delegate, hWnd, uMsg, wParam, lParam);
    }

    public int callDefaultWndProc(Pointer hWnd, int uMsg, int wParam, int lParam)
    {
        return CommonWndProc.user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
    }


    public boolean isMovingOrSizing()
    {
        return movingOrSizing;
    }

    void setMovingOrSizing(boolean movingOrSizing)
    {
        this.movingOrSizing = movingOrSizing;
    }

    public boolean isDragAppBarWidthWindow()
    {
        return dragAppBarWidthWindow;
    }

    public void setDragAppBarWidthWindow(boolean dragAppBarWidthWindow)
    {
        this.dragAppBarWidthWindow = dragAppBarWidthWindow;
    }

    public DragGuide getDragGuide()
    {
        return dragGuide;
    }

    public DesktopEnvironment getDesktopEnvironment()
    {
        return environment;
    }

    public AppBarModel getAppBarModel()
    {
        return model;
    }

    public WindowMessageHandler getWindowMessageHandler()
    {
        return windowMessageHandler;
    }

    public AppBar getAppBar()
    {
        return appbar;
    }
}
